#include "applyfriend.h"
#include "ui_applyfriend.h"
#include <QScrollBar>
#include "global.h"
#include "usermgr.h"
#include "tcpmgr.h"
#include "QJsonDocument"


// ApplyFriend 类的构造函数，用于初始化加好友对话框
ApplyFriend::ApplyFriend(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::ApplyFriend),_label_point(2,6)
{
    // 设置 UI
    ui->setupUi(this);
    // 隐藏对话框的标题栏，实现无标题栏窗口
    setWindowFlags(windowFlags() | Qt::FramelessWindowHint);
    // 设置对话框的对象名称，便于样式表设置
    this->setObjectName("ApplyFriend");
     // 设置对话框为模态对话框，即对话框显示时，用户不能与其他窗口交互
    this->setModal(true);
    ui->name_ed->setPlaceholderText(tr("恋恋风辰"));
    ui->lb_ed->setPlaceholderText("搜索、添加标签");
    ui->back_ed->setPlaceholderText("燃烧的胸毛");

    ui->lb_ed->SetMaxLength(21);
    ui->lb_ed->move(2, 2);
    ui->lb_ed->setFixedHeight(20);
    ui->lb_ed->setMaxLength(10);
    ui->input_tip_wid->hide();

    _tip_cur_point = QPoint(5, 5);

      // 初始化标签数据，包含一系列预设的标签
    _tip_data = { "同学","家人","菜鸟教程","C++ Primer","Rust 程序设计",
                 "父与子学Python","nodejs开发指南","go 语言开发指南",
                 "游戏伙伴","金融投资","微信读书","拼多多拼友" };

    connect(ui->more_lb, &ClickedOnceLabel::clicked, this, &ApplyFriend::ShowMoreLabel);
    InitTipLbs();
    // 连接标签输入框的回车信号到 SlotLabelEnter 槽函数
    connect(ui->lb_ed, &CustomizeEdit::returnPressed, this, &ApplyFriend::SlotLabelEnter);
    // 连接标签输入框的文本变化信号到 SlotLabelTextChange 槽函数
    connect(ui->lb_ed, &CustomizeEdit::textChanged, this, &ApplyFriend::SlotLabelTextChange);
    // 连接标签输入框的编辑完成信号到 SlotLabelEditFinished 槽函数
    connect(ui->lb_ed, &CustomizeEdit::editingFinished, this, &ApplyFriend::SlotLabelEditFinished);
    // 连接提示标签的点击信号到 SlotAddFirendLabelByClickTip 槽函数
    connect(ui->tip_lb, &ClickedOnceLabel::clicked, this, &ApplyFriend::SlotAddFirendLabelByClickTip);


    ui->scrollArea->horizontalScrollBar()->setHidden(true);
    ui->scrollArea->verticalScrollBar()->setHidden(true);
    ui->scrollArea->installEventFilter(this);
    ui->sure_btn->SetState("normal","hover","press");
    ui->cancel_btn->SetState("normal","hover","press");



    //连接确认和取消按钮的槽函数
    connect(ui->cancel_btn, &QPushButton::clicked, this, &ApplyFriend::SlotApplyCancel);
    connect(ui->sure_btn, &QPushButton::clicked, this, &ApplyFriend::SlotApplySure);
}

// 初始化标签显示的函数
void ApplyFriend::InitTipLbs()
{
    // 初始化行数为 1
    int lines = 1;
    for(int i = 0; i < _tip_data.size(); i++){

        auto* lb = new ClickedLabel(ui->lb_list);
        // 设置标签的不同状态样式
        lb->SetState("normal", "hover", "pressed", "selected_normal",
                     "selected_hover", "selected_pressed");
        // 设置标签的对象名称
        lb->setObjectName("tipslb");
        // 设置标签的文本
        lb->setText(_tip_data[i]);
        // 连接标签的点击信号到 SlotChangeFriendLabelByTip 槽函数
        connect(lb, &ClickedLabel::clicked, this, &ApplyFriend::SlotChangeFriendLabelByTip);

        QFontMetrics fontMetrics(lb->font()); // 获取QLabel控件的字体信息
        int textWidth = fontMetrics.horizontalAdvance (lb->text()); // 获取文本的宽度
        int textHeight = fontMetrics.height(); // 获取文本的高度

        if (_tip_cur_point.x() + textWidth + tip_offset > ui->lb_list->width()) {
            lines++;
            if (lines > 2) {
                delete lb;
                return;
            }

            _tip_cur_point.setX(tip_offset);
            _tip_cur_point.setY(_tip_cur_point.y() + textHeight + 15);

        }

        auto next_point = _tip_cur_point;

        AddTipLbs(lb, _tip_cur_point,next_point, textWidth, textHeight);

        _tip_cur_point = next_point;
    }

}

void ApplyFriend::AddTipLbs(ClickedLabel *lb, QPoint cur_point, QPoint &next_point, int text_width, int text_height)
{
    // 将标签移动到当前指定的位置
    lb->move(cur_point);
    // 显示标签
    lb->show();

    // 将标签添加到已添加的标签映射中，键为标签的文本内容，值为标签对象指针
    _add_labels.insert(lb->text(), lb);
    // 将标签的文本内容添加到已添加标签的键列表中
    _add_label_keys.push_back(lb->text());

    // 计算下一个标签的起始 x 坐标，当前标签的 x 坐标加上文本宽度再加上间距
    next_point.setX(lb->pos().x() + text_width + 15);
    // 下一个标签的 y 坐标与当前标签的 y 坐标保持一致
    next_point.setY(lb->pos().y());
}

//eventFilter 是 Qt 框架中用于事件过滤的机制，其作用是拦截并处理特定对象的事件。
bool ApplyFriend::eventFilter(QObject *obj, QEvent *event)
{
    if (obj == ui->scrollArea && event->type() == QEvent::Enter)
    {
        ui->scrollArea->verticalScrollBar()->setHidden(false);
    }
    else if (obj == ui->scrollArea && event->type() == QEvent::Leave)
    {
        ui->scrollArea->verticalScrollBar()->setHidden(true);
    }
    return QObject::eventFilter(obj, event);
}

//后期搜索用户功能用户数据会从服务器传回来，所以写了下面的接口
void ApplyFriend::SetSearchInfo(std::shared_ptr<SearchInfo> si)
{
    _si = si;
    auto applyname = UserMgr::GetInstance()->GetName();
    auto bakname = si->_name;
    ui->name_ed->setText(applyname);
    ui->back_ed->setText(bakname);
}

void ApplyFriend::SlotApplySure()
{
    qDebug()<<"Slot Apply Sure called" ;
    //发送请求逻辑
    QJsonObject jsonObj;
    auto uid = UserMgr::GetInstance()->GetUid();
    jsonObj["uid"] = uid;
    auto name = ui->name_ed->text();
    if(name.isEmpty()){
        name = ui->name_ed->placeholderText();
    }

    jsonObj["applyname"] = name;

    auto bakname = ui->back_ed->text();
    if(bakname.isEmpty()){
        bakname = ui->back_ed->placeholderText();
    }

    jsonObj["bakname"] = bakname;
    jsonObj["touid"] = _si->_uid;

    QJsonDocument doc(jsonObj);
    QByteArray jsonData = doc.toJson(QJsonDocument::Compact);

    //发送tcp请求给chat server
    emit TcpMgr::GetInstance()->sig_send_data(ReqId::ID_ADD_FRIEND_REQ, jsonData);
    this->hide();
    deleteLater();
}


void ApplyFriend::ShowMoreLabel()
{
    // 输出调试信息，表明接收到“显示更多标签”的点击事件
    qDebug()<< "receive more label clicked";
    // 隐藏用于显示“更多”的标签所在的窗口部件
    ui->more_lb_wid->hide();

    // 设置标签列表的固定宽度为 325 像素
    ui->lb_list->setFixedWidth(325);
    // 设置当前标签的起始位置为 (5, 5)
    _tip_cur_point = QPoint(5, 5);
    // 初始化下一个标签的起始位置为当前标签的起始位置
    auto next_point = _tip_cur_point;
    int textWidth;
    int textHeight;

    // 重排现有的标签
    for(auto & added_key : _add_label_keys){
        // 根据标签的键从已添加标签的映射中获取对应的标签指针
        auto added_lb = _add_labels[added_key];

        // 获取标签的字体信息，用于后续计算文本的宽度和高度
        QFontMetrics fontMetrics(added_lb->font());
        // 计算标签文本的宽度
        textWidth = fontMetrics.horizontalAdvance(added_lb->text());
        // 计算标签文本的高度
        textHeight = fontMetrics.height();

        // 判断如果当前标签的起始 x 坐标加上文本宽度再加上偏移量超出了标签列表的宽度
        if(_tip_cur_point.x() + textWidth + tip_offset > ui->lb_list->width()){
            // 将下一个标签的起始 x 坐标设置为偏移量
            _tip_cur_point.setX(tip_offset);
            // 将下一个标签的起始 y 坐标设置为当前 y 坐标加上文本高度和额外的间距
            _tip_cur_point.setY(_tip_cur_point.y() + textHeight + 15);
        }
        // 将当前标签移动到新的位置
        added_lb->move(_tip_cur_point);

        // 计算下一个标签的起始 x 坐标，为当前标签的 x 坐标加上文本宽度和间距
        next_point.setX(added_lb->pos().x() + textWidth + 15);
        // 下一个标签的 y 坐标与当前标签的 y 坐标保持一致
        next_point.setY(_tip_cur_point.y());

        // 更新当前标签的起始位置为下一个标签的起始位置
        _tip_cur_point = next_point;
    }

    // 添加未添加的标签
    for(int i = 0; i < _tip_data.size(); i++){
        // 在已添加标签的映射中查找当前标签的数据
        auto iter = _add_labels.find(_tip_data[i]);
        // 如果该标签已经存在于已添加标签的映射中，则跳过本次循环
        if(iter != _add_labels.end()){
            continue;
        }

        // 创建一个新的 ClickedLabel 标签，并将其父窗口设置为标签列表
        auto* lb = new ClickedLabel(ui->lb_list);
        // 设置标签的不同状态样式
        lb->SetState("normal", "hover", "pressed", "selected_normal",
                     "selected_hover", "selected_pressed");
        // 设置标签的对象名称
        lb->setObjectName("tipslb");
        // 设置标签的文本内容
        lb->setText(_tip_data[i]);
        // 连接标签的点击信号到 ApplyFriend 类的 SlotChangeFriendLabelByTip 槽函数
        connect(lb, &ClickedLabel::clicked, this, &ApplyFriend::SlotChangeFriendLabelByTip);

        // 获取新标签的字体信息，用于计算文本的宽度和高度
        QFontMetrics fontMetrics(lb->font());
        // 计算新标签文本的宽度
        int textWidth = fontMetrics.horizontalAdvance(lb->text());
        // 计算新标签文本的高度
        int textHeight = fontMetrics.height();

        // 判断如果当前标签的起始 x 坐标加上文本宽度再加上偏移量超出了标签列表的宽度
        if (_tip_cur_point.x() + textWidth + tip_offset > ui->lb_list->width()) {
            // 将下一个标签的起始 x 坐标设置为偏移量
            _tip_cur_point.setX(tip_offset);
            // 将下一个标签的起始 y 坐标设置为当前 y 坐标加上文本高度和额外的间距
            _tip_cur_point.setY(_tip_cur_point.y() + textHeight + 15);
        }

        // 更新下一个标签的起始位置为当前标签的起始位置
        next_point = _tip_cur_point;

        // 调用 AddTipLbs 函数将新标签添加到界面中
        AddTipLbs(lb, _tip_cur_point, next_point, textWidth, textHeight);

        // 更新当前标签的起始位置为下一个标签的起始位置
        _tip_cur_point = next_point;
    }

    // 计算标签列表需要增加的高度，即最后一个标签的 y 坐标加上文本高度和偏移量与当前标签列表高度的差值
    int diff_height = next_point.y() + textHeight + tip_offset - ui->lb_list->height();
    // 设置标签列表的固定高度为最后一个标签的 y 坐标加上文本高度和偏移量
    ui->lb_list->setFixedHeight(next_point.y() + textHeight + tip_offset);

    // 输出调试信息，可取消注释用于查看调整后标签列表的大小
    //qDebug()<<"after resize ui->lb_list size is " <<  ui->lb_list->size();
    // 调整滚动内容区域的高度，使其能够容纳所有标签
    ui->scrollcontent->setFixedHeight(ui->scrollcontent->height() + diff_height);
}


ApplyFriend::~ApplyFriend()
{
    qDebug()<< "ApplyFriend destruct";
    delete ui;
}

void ApplyFriend::resetLabels()
{
    auto max_width = ui->gridWidget->width();
    auto label_height = 0;
    int total_width = 0; // 用于统计所有标签的总宽度

    for(auto iter = _friend_labels.begin(); iter != _friend_labels.end(); iter++){
        // 累加当前标签的宽度和间距到总宽度
        total_width += iter.value()->width() + 2;

        // 判断如果当前标签的起始 x 坐标加上当前标签的宽度超过了网格部件的最大宽度
        if( _label_point.x() + iter.value()->width() > max_width) {
            // 则将标签的起始位置移动到下一行
            // 更新 y 坐标，在当前 y 坐标基础上加上当前标签的高度和额外的间距 6
            _label_point.setY(_label_point.y() + iter.value()->height() + 6);
            // 将 x 坐标重置为 2，作为新一行的起始位置
            _label_point.setX(2);
            // 新的一行开始，重置总宽度统计
            total_width = iter.value()->width() + 2;
        }

        // 将当前标签移动到计算好的位置
        iter.value()->move(_label_point);
        // 显示当前标签
        iter.value()->show();

        // 更新 _label_point 的 x 坐标，为下一个标签的放置做准备
        // 在当前 x 坐标基础上加上当前标签的宽度和额外的间距 2
        _label_point.setX(_label_point.x() + iter.value()->width() + 2);
        // y 坐标保持不变
        _label_point.setY(_label_point.y());
        // 更新 label_height 为当前标签的高度
        label_height = iter.value()->height();
    }

    // 如果 _friend_labels 容器为空
    if(_friend_labels.isEmpty()){
        // 将输入框 ui->lb_ed 移动到当前 _label_point 位置
        ui->lb_ed->move(_label_point);
        // 直接返回，结束函数执行
        return;
    }

    // 判断如果当前 _label_point 的 x 坐标加上输入框的最小长度超过了网格部件的宽度
    if(_label_point.x() + MIN_APPLY_LABEL_ED_LEN > ui->gridWidget->width()){
        // 则将输入框 ui->lb_ed 移动到新的一行
        // x 坐标为 2，y 坐标为当前 y 坐标加上当前标签的高度和额外的间距 6
        ui->lb_ed->move(2, _label_point.y() + label_height + 6);
    } else {
        // 如果没有超过最大宽度，将输入框 ui->lb_ed 移动到当前 _label_point 位置
        ui->lb_ed->move(_label_point);
    }

    // 可以在这里使用统计的总宽度进行后续操作，例如打印输出
    qDebug() << "Total width of all labels: " << total_width;
}


// 该函数用于向界面添加一个新的好友标签
void ApplyFriend::addLabel(QString name)
{
    // 检查要添加的标签是否已经存在于 _friend_labels 容器中
    // 如果存在，则直接返回，避免重复添加
    if (_friend_labels.find(name) != _friend_labels.end()) {
        return;
    }

    // 创建一个新的 FriendLabel 对象，并将其父窗口设置为 ui->gridWidget
    auto tmplabel = new FriendLabel(ui->gridWidget);

    // 设置标签显示的文本内容
    tmplabel->SetText(name);
    // 设置标签的对象名称，方便后续查找和样式设置
    tmplabel->setObjectName("FriendLabel");

    // 获取网格窗口部件的宽度，作为布局的最大宽度限制
    auto max_width = ui->gridWidget->width();

    // 这里可以添加对已布局标签宽度的统计逻辑，目前是待完成的任务
    // todo... 添加宽度统计

    // 判断当前布局的 x 坐标加上新标签的宽度是否超过了网格窗口部件的最大宽度
    if (_label_point.x() + tmplabel->width() > max_width) {
        // 如果超过最大宽度，需要换行布局
        // 更新 y 坐标，将其设置为当前 y 坐标加上新标签的高度和额外的间距 6
        _label_point.setY(_label_point.y() + tmplabel->height() + 6);
        // 将 x 坐标重置为 2，作为新一行的起始位置
        _label_point.setX(2);
    }
    else {
        // 如果未超过最大宽度，不需要换行，保持当前布局位置不变
        // 这里可以添加一些额外逻辑，目前为空
    }

    // 将新创建的标签移动到计算好的布局位置
    tmplabel->move(_label_point);
    // 显示新创建的标签
    tmplabel->show();

    // 将新标签添加到 _friend_labels 容器中，键为标签的文本内容，值为标签对象指针
    _friend_labels[tmplabel->Text()] = tmplabel;
    // 将新标签的文本内容添加到 _friend_label_keys 容器中，用于记录标签的添加顺序
    _friend_label_keys.push_back(tmplabel->Text());

    // 连接新标签的关闭信号 sig_close 到当前类的 SlotRemoveFriendLabel 槽函数
    // 当标签发出关闭信号时，会触发该槽函数进行相应处理
    connect(tmplabel, &FriendLabel::sig_close, this, &ApplyFriend::SlotRemoveFriendLabel);

    // 更新当前布局的 x 坐标，为下一个标签的布局做准备
    // 在当前 x 坐标基础上加上新标签的宽度和额外的间距 2
    _label_point.setX(_label_point.x() + tmplabel->width() + 2);

    // 判断当前布局的 x 坐标加上输入框的最小长度是否超过了网格窗口部件的宽度
    if (_label_point.x() + MIN_APPLY_LABEL_ED_LEN > ui->gridWidget->width()) {
        // 如果超过最大宽度，将输入框移动到新的一行
        // x 坐标设置为 2，y 坐标设置为当前 y 坐标加上新标签的高度和额外的间距 2
        ui->lb_ed->move(2, _label_point.y() + tmplabel->height() + 2);
    }
    else {
        // 如果未超过最大宽度，将输入框移动到当前布局位置
        ui->lb_ed->move(_label_point);
    }

    // 清空输入框中的内容，方便用户输入下一个标签名称
    ui->lb_ed->clear();

    // 判断网格窗口部件的当前高度是否小于当前布局的 y 坐标加上新标签的高度和额外的间距 2
    if (ui->gridWidget->height() < _label_point.y() + tmplabel->height() + 2) {
        // 如果小于，则调整网格窗口部件的高度
        // 将高度设置为当前布局的 y 坐标加上新标签高度的两倍和额外的间距 2
        ui->gridWidget->setFixedHeight(_label_point.y() + tmplabel->height() * 2 + 2);
    }
}


// 此函数作为槽函数，通常在用户输入标签内容并触发相应事件（如按下回车键）时被调用
void ApplyFriend::SlotLabelEnter()
{
    // 检查输入框中的文本是否为空，如果为空则直接返回，不进行后续操作
    if(ui->lb_ed->text().isEmpty()){
        return;
    }

    // 获取输入框中的文本内容
    auto text = ui->lb_ed->text();
    // 调用 addLabel 函数将输入的文本作为标签添加到界面中
    addLabel(ui->lb_ed->text());

    // 隐藏输入提示窗口，可能用于提示用户输入的提示信息不再需要显示
    ui->input_tip_wid->hide();

    // 在 _tip_data 容器中查找输入的文本
    auto find_it = std::find(_tip_data.begin(), _tip_data.end(), text);
    // 如果在 _tip_data 中没有找到该文本
    if (find_it == _tip_data.end()) {
        // 将该文本添加到 _tip_data 容器中，记录该标签已被使用
        _tip_data.push_back(text);
    }

    // 在 _add_labels 映射中查找该文本对应的标签
    auto find_add = _add_labels.find(text);
    // 如果在 _add_labels 中找到了对应的标签
    if (find_add != _add_labels.end()) {
        // 将该标签的状态设置为选中状态
        find_add.value()->SetCurState(ClickLbState::Selected);
        // 直接返回，不再进行后续添加标签的操作
        return;
    }

    // 如果在 _add_labels 中未找到对应的标签，则需要在标签展示栏添加新标签

    // 创建一个新的 ClickedLabel 标签，并将其父窗口设置为 ui->lb_list
    auto* lb = new ClickedLabel(ui->lb_list);
    // 设置标签在不同状态下的样式
    lb->SetState("normal", "hover", "pressed", "selected_normal",
                 "selected_hover", "selected_pressed");
    // 设置标签的对象名称，方便后续查找和样式设置
    lb->setObjectName("tipslb");
    // 设置标签显示的文本内容为输入的文本
    lb->setText(text);
    // 连接标签的点击信号到当前类的 SlotChangeFriendLabelByTip 槽函数
    connect(lb, &ClickedLabel::clicked, this, &ApplyFriend::SlotChangeFriendLabelByTip);

    // 输出调试信息，显示标签列表的宽度
    qDebug() << "ui->lb_list->width() is " << ui->lb_list->width();
    // 输出调试信息，显示当前标签布局的 x 坐标
    qDebug() << "_tip_cur_point.x() is " << _tip_cur_point.x();

    // 获取标签的字体信息，用于计算文本的宽度和高度
    QFontMetrics fontMetrics(lb->font());
    // 计算标签文本的宽度
    int textWidth = fontMetrics.horizontalAdvance (lb->text());
    // 计算标签文本的高度
    int textHeight = fontMetrics.height();
    // 输出调试信息，显示标签文本的宽度
    qDebug() << "textWidth is " << textWidth;

    // 判断当前标签布局的 x 坐标加上文本宽度、偏移量和额外间距是否超过标签列表的宽度
    if (_tip_cur_point.x() + textWidth + tip_offset + 3 > ui->lb_list->width()) {
        // 如果超过宽度，则将标签布局的 x 坐标重置为 5，开始新的一行布局
        _tip_cur_point.setX(5);
        // 将标签布局的 y 坐标更新为当前 y 坐标加上文本高度和额外间距 15
        _tip_cur_point.setY(_tip_cur_point.y() + textHeight + 15);
    }

    // 记录下一个标签的起始位置为当前标签布局位置
    auto next_point = _tip_cur_point;

    // 调用 AddTipLbs 函数将新标签添加到界面中，并更新布局位置
    AddTipLbs(lb, _tip_cur_point, next_point, textWidth, textHeight);
    // 更新当前标签布局位置为下一个标签的起始位置
    _tip_cur_point = next_point;

    // 计算标签列表需要增加的高度，即下一个标签的 y 坐标加上文本高度和偏移量与当前标签列表高度的差值
    int diff_height = next_point.y() + textHeight + tip_offset - ui->lb_list->height();
    // 设置标签列表的固定高度为下一个标签的 y 坐标加上文本高度和偏移量
    ui->lb_list->setFixedHeight(next_point.y() + textHeight + tip_offset);

    // 将新添加的标签状态设置为选中状态
    lb->SetCurState(ClickLbState::Selected);

    // 调整滚动内容区域的高度，使其能够容纳所有标签
    ui->scrollcontent->setFixedHeight(ui->scrollcontent->height() + diff_height);
}


void ApplyFriend::SlotRemoveFriendLabel(QString name)
{
    qDebug() << "receive close signal";

    _label_point.setX(2);
    _label_point.setY(6);

    auto find_iter = _friend_labels.find(name);

    if(find_iter == _friend_labels.end()){
        return;
    }

    auto find_key = _friend_label_keys.end();
    for(auto iter = _friend_label_keys.begin(); iter != _friend_label_keys.end();
         iter++){
        if(*iter == name){
            find_key = iter;
            break;
        }
    }

    if(find_key != _friend_label_keys.end()){
        _friend_label_keys.erase(find_key);
    }


    delete find_iter.value();

    _friend_labels.erase(find_iter);

    resetLabels();

    auto find_add = _add_labels.find(name);
    if(find_add == _add_labels.end()){
        return;
    }

    find_add.value()->ResetNormalState();
}


//点击标已有签添加或删除新联系人的标签
void ApplyFriend::SlotChangeFriendLabelByTip(QString lbtext, ClickLbState state)
{
    auto find_iter = _add_labels.find(lbtext);
    if(find_iter == _add_labels.end()){
        return;
    }

    if(state == ClickLbState::Selected){
        //编写添加逻辑
        addLabel(lbtext);
        return;
    }

    if(state == ClickLbState::Normal){
        //编写删除逻辑
        SlotRemoveFriendLabel(lbtext);
        return;
    }

}


void ApplyFriend::SlotLabelTextChange(const QString& text)
{
    if (text.isEmpty()) {
        ui->tip_lb->setText("");
        ui->input_tip_wid->hide();
        return;
    }

    auto iter = std::find(_tip_data.begin(), _tip_data.end(), text);
    if (iter == _tip_data.end()) {
        auto new_text = add_prefix + text;
        ui->tip_lb->setText(new_text);
        ui->input_tip_wid->show();
        return;
    }
    ui->tip_lb->setText(text);
    ui->input_tip_wid->show();
}

void ApplyFriend::SlotLabelEditFinished()
{
    ui->input_tip_wid->hide();
}


void ApplyFriend::SlotAddFirendLabelByClickTip(QString text)
{
    int index = text.indexOf(add_prefix);
    if (index != -1) {
        text = text.mid(index + add_prefix.length());
    }
    addLabel(text);

    auto find_it = std::find(_tip_data.begin(), _tip_data.end(), text);
    //找到了就只需设置状态为选中即可
    if (find_it == _tip_data.end()) {
        _tip_data.push_back(text);
    }

    //判断标签展示栏是否有该标签
    auto find_add = _add_labels.find(text);
    if (find_add != _add_labels.end()) {
        find_add.value()->SetCurState(ClickLbState::Selected);
        return;
    }

    //标签展示栏也增加一个标签, 并设置绿色选中
    auto* lb = new ClickedLabel(ui->lb_list);
    lb->SetState("normal", "hover", "pressed", "selected_normal",
                 "selected_hover", "selected_pressed");
    lb->setObjectName("tipslb");
    lb->setText(text);
    connect(lb, &ClickedLabel::clicked, this, &ApplyFriend::SlotChangeFriendLabelByTip);
    qDebug() << "ui->lb_list->width() is " << ui->lb_list->width();
    qDebug() << "_tip_cur_point.x() is " << _tip_cur_point.x();

    QFontMetrics fontMetrics(lb->font()); // 获取QLabel控件的字体信息
    int textWidth = fontMetrics.horizontalAdvance(lb->text()); // 获取文本的宽度
    int textHeight = fontMetrics.height(); // 获取文本的高度
    qDebug() << "textWidth is " << textWidth;

    if (_tip_cur_point.x() + textWidth+ tip_offset+3 > ui->lb_list->width()) {

        _tip_cur_point.setX(5);
        _tip_cur_point.setY(_tip_cur_point.y() + textHeight + 15);

    }

    auto next_point = _tip_cur_point;

    AddTipLbs(lb, _tip_cur_point, next_point, textWidth,textHeight);
    _tip_cur_point = next_point;

    int diff_height = next_point.y() + textHeight + tip_offset - ui->lb_list->height();
    ui->lb_list->setFixedHeight(next_point.y() + textHeight + tip_offset);

    lb->SetCurState(ClickLbState::Selected);

    ui->scrollcontent->setFixedHeight(ui->scrollcontent->height()+ diff_height );
}


void ApplyFriend::SlotApplyCancel()
{
    qDebug() << "Slot Apply Cancel";
    this->hide();
    deleteLater();
}


